package com.listeningframework.boot.commons.http;

import com.google.common.collect.Maps;
import com.listeningframework.boot.commons.string.JacksonUtils;
import com.listeningframework.boot.commons.string.StringUtils;
import com.listeningframework.boot.commons.utils.DateFormatUtils;
import org.apache.commons.io.IOUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.Writer;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Map;

public class HttpWebUtils {
    /**
     * Construct
     */
    private HttpWebUtils() {

    }

    /**
     * 是否跨域请求
     *
     * @param request HttpServletRequest
     * @return boolean
     */
    public static boolean isCorsRequest(HttpServletRequest request) {
        return (request.getHeader(HttpHeaders.ORIGIN.getCode()) != null);
    }

    /**
     * 是否为PreFight请求
     *
     * @param request HttpServletRequest
     * @return boolean
     */
    public static boolean isPreFlightRequest(HttpServletRequest request) {
        String reqMethod = request.getMethod();
        String optionsMethod = HttpMethod.OPTIONS.name();
        boolean isMethodOptions = org.apache.commons.lang3.StringUtils.equalsIgnoreCase(optionsMethod, reqMethod);
        boolean isCorsRequest = isCorsRequest(request);
        String requestheader = request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD.getCode());
        return (isCorsRequest && isMethodOptions && requestheader != null);
    }

    /**
     * Allow Cors Once
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     */
    public static final void allowCorsOnce(HttpServletRequest request, HttpServletResponse response) {
        String origin = request.getHeader(HttpHeaders.ORIGIN.getCode());
        response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN.getCode(), origin);
        response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS.getCode(), "true");
    }

    /**
     * Get Request IP Address
     *
     * @param request HttpServletRequest
     * @return String
     */
    public static final String getRequestIP(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * Get Local Machine IP
     *
     * @return String
     */
    public static final String getLocalIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            throw new RuntimeException("Get Local IP Fail", e);
        }
    }

    public static void setViewHeader(HttpServletResponse response, String contentType) {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType(contentType + ";charset=gb2312");
    }

    /**
     * Set File Download Header
     *
     * @param response HttpServletResponse
     * @param fileName 文件名
     * @param fileLength 文件长度
     */
    public static void setDownloadHeader(HttpServletResponse response, String fileName, Long fileLength) {
        response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes()));
        response.addHeader("Content-Length", "" + fileLength);
    }

    /**
     * Get Http Servlet Session
     *
     * @param request HttpServletRequest
     * @return HttpSession
     */
    public static HttpSession getSession(HttpServletRequest request) {
        return request.getSession();
    }

    /**
     * 是否为Ajax请求
     *
     * @param request HttpServletRequest
     * @return boolean
     */
    public static boolean isAjaxRequest(HttpServletRequest request) {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
    }

    /**
     * 是否为Get Or Post
     *
     * @param request HttpServletRequest
     * @return boolean
     */
    public static boolean isGetOrPostMethod(HttpServletRequest request) {
        String method = request.getMethod();
        return StringUtils.equalsIgnoreCase(method, "GET") || StringUtils.equalsIgnoreCase(method, "POST");
    }

    /**
     * Get Param Value From HttpServletRequest
     *
     * @param request HttpServletRequest
     * @param param 参数名
     * @return String
     */
    public static final String getValue(HttpServletRequest request, String param) {
        return getValue(request, param, "");
    }

    /**
     * Get Param Value From HttpServletRequest
     *
     * @param request HttpServletRequest
     * @param param 参数名
     * @param def 默认值
     * @return String
     */
    public static final String getValue(HttpServletRequest request, String param, String def) {
        if (request == null || StringUtils.isBlank(param)) {
            return def;
        }
        Object paramValue = request.getParameter(param);
        if (paramValue == null) {
            return def;
        }
        return String.valueOf(paramValue).trim();
    }

    /**
     * Get Integer Value From ParamMap
     *
     * @param request HttpServletRequest
     * @param paramCode 参数名
     * @param def 默认值
     * @return Integer
     */
    public static final Integer getIntValue(HttpServletRequest request, String paramCode, Integer def) {
        String value = getValue(request, paramCode);
        return StringUtils.getIntValue(value, def);
    }

    /**
     * Get Integer Value From request
     *
     * @param request HttpServletRequest
     * @param paramCode 参数名
     * @return Integer
     */
    public static final Integer getIntValue(HttpServletRequest request, String paramCode) {
        return getIntValue(request, paramCode, null);
    }

    /**
     * Get Long Value From Request
     *
     * @param request HttpServletRequest
     * @param paramCode 参数名
     * @param def 默认值
     * @return Long
     */
    public static final Long getLongValue(HttpServletRequest request, String paramCode, Long def) {
        String value = getValue(request, paramCode);
        return StringUtils.getLongValue(value, def);
    }

    /**
     * Get Long Value From ParamMap
     *
     * @param request HttpServletRequest
     * @param paramCode 参数名
     * @return Long
     */
    public static final Long getLongValue(HttpServletRequest request, String paramCode) {
        return getLongValue(request, paramCode, null);
    }

    /**
     * Get Date Value From Request
     *
     * @param request HttpServletRequest
     * @param paramCode 参数名
     * @param format 默认格式
     * @return Date
     */
    public static final Date getDateValue(HttpServletRequest request, String paramCode, String format) {
        String value = getValue(request, paramCode);
        return DateFormatUtils.string2date(value, format);
    }

    /**
     * Get Date Value From Request
     *
     * @param request   HttpServletRequest
     * @param paramCode 参数名
     * @return Date
     */
    public static final Date getDateValue(HttpServletRequest request, String paramCode) {
        return getDateValue(request, paramCode, "yyyy-MM-dd");
    }

    /**
     * Write Content To Response
     *
     * @param response HttpServletResponse
     * @param content 内容
     */
    public static void writeJson(HttpServletResponse response, String content) {
        try {
            response.setHeader("Content-Type", "application/json;charset=UTF-8");
            Writer writer = response.getWriter();
            writer.write(content);
            writer.flush();
        } catch (Exception e) {
            throw new RuntimeException("write content to response fail", e);
        }
    }

    /**
     * Write Message To Response
     *
     * @param response HttpServletResponse
     * @param result 结果状态
     * @param message 信息
     */
    public static void writeJson(HttpServletResponse response, boolean result, String message) {
        Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.put("result", result);
        resultMap.put("message", message);
        writeJson(response, JacksonUtils.toJson(resultMap));
    }

    /**
     * Get Session Value
     *
     * @param request HttpServletRequest
     * @param paramCode 参数名
     * @return String
     */
    public static String getSessionValue(HttpServletRequest request, String paramCode) {
        if (request == null || StringUtils.isBlank(paramCode)) {
            return null;
        }
        Object paramValue = request.getSession().getAttribute(paramCode);
        if (paramValue == null) {
            return null;
        }
        return String.valueOf(paramValue).trim();
    }
}
